package com.casstime.ec.cloud.discount.rule;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import com.casstime.ec.cloud.discount.model.AmountCalcResp;
import com.casstime.ec.cloud.discount.model.DiscountRuleParam;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotion;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionConfig;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionConfigAmount;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionConfigArea;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionConfigBrand;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionConfigCategory;
import com.casstime.ec.cloud.values.amountPromotion.OrderProductParam;
import com.casstime.ec.cloud.values.amountPromotion.enums.DiscountConfigValueEnum;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**  
 * ClassName: AfterSalesPolicyRule 
 * Function: 这个类是用来计算策略规则的
 * Reason: ADD REASON(可选).
 *  
 * @author wu.chen 
 * 2017年2月8日 下午5:46:59
 * @version   
 * @since JDK 1.8
 */
@Service
public class DiscountPolicyRule {
	
	public AmountCalcResp calcCutFormProduct(AmountPromotion p, BigDecimal price) {
		AmountCalcResp resp = new AmountCalcResp();
		int retValue = 0;
		int retRequire = 0;
		String retAmountId = "";
		int nextValue = 0;
		int nextRequire = 0;
		if (DiscountConfigValueEnum.FULLCUT_NORMAL.getIndex().equals(p.getPromotionType())) {
			for (AmountPromotionConfigAmount amount : p.getPromotionAmounts()) {
				int require = Integer.parseInt(amount.getRequireAmount());
				int cut = Integer.parseInt(amount.getOffAmount());
				if (price.compareTo(new BigDecimal(require)) >= 0 && cut > retValue) {
					retValue = cut;
					retRequire = require;
					retAmountId = amount.getId();
					nextValue = retValue;
					nextRequire = retRequire;
				}
			}
			int tempNextRequire = nextRequire;
			int tempNextValue = nextValue;
			for (AmountPromotionConfigAmount amount : p.getPromotionAmounts()) {
				int temp = Integer.parseInt(amount.getRequireAmount());
				if ((tempNextRequire > temp  || tempNextRequire == 0 || tempNextRequire == retRequire) && nextRequire < temp) {
					tempNextRequire = temp;
					tempNextValue = Integer.parseInt(amount.getOffAmount());
				}
			}
			nextValue = tempNextValue;
			nextRequire = tempNextRequire;
		} else if (DiscountConfigValueEnum.FULLCUT_PER.getIndex().equals(p.getPromotionType())) {
			AmountPromotionConfigAmount amount = p.getPromotionAmounts().get(0);
			int require = Integer.parseInt(amount.getRequireAmount());
			int cut = Integer.parseInt(amount.getOffAmount());
			for (int i = 1; i < 100; i++) {
				nextValue = i * cut;
				nextRequire = i * require;
				if (price.compareTo(new BigDecimal(i * require)) >= 0) {
					retValue = cut * i;
					retRequire = require * i;
					retAmountId = amount.getId();
					nextValue = (i + 1) * cut;
					nextRequire = (i + 1) * require;
				} else {
					break;
				}
			}
		}
		AmountPromotionConfigAmount  currentAmount = new AmountPromotionConfigAmount();
		currentAmount.setId(retAmountId);
		currentAmount.setAmountOffType(retValue + "");
		currentAmount.setRequireAmount(retRequire + "");
		
		AmountPromotionConfigAmount  nextAmount = new AmountPromotionConfigAmount();
		nextAmount.setAmountOffType(nextValue + "");
		nextAmount.setRequireAmount(nextRequire + "");
		
		resp.setTotalCut(retValue);
		resp.setCurrentAmount(currentAmount);
		resp.setNextAmount(nextAmount);
		return resp;
	}
	
	public BigDecimal doCalcPerCut(int totalDiscount, List<OrderProductParam> products) {
		BigDecimal retCut = BigDecimal.ZERO;
		int remain = totalDiscount;
		if (CollectionUtils.isEmpty(products)) {
			return retCut;
		}
		BigDecimal totalDiscountAmount = new BigDecimal(totalDiscount);
		BigDecimal totalAmount = BigDecimal.ZERO;
		for (OrderProductParam product : products) {
			totalAmount = totalAmount.add(product.getProductPrice().multiply(new BigDecimal(product.getProductNumber())));
			product.setAfterFullCutPrice(product.getProductPrice());
		}
		
		List<OrderProductParam> tempSorted = products.stream()
				.sorted(Comparator.comparing(OrderProductParam::getProductPrice).reversed()).collect(Collectors.toList());
		for (OrderProductParam product : tempSorted) {
			if (product.getProductNumber() == 0) {
				continue;
			}
			if (remain > 0 && remain >= product.getProductNumber()) {
				int perCut = product.getProductPrice().multiply(totalDiscountAmount).divide(totalAmount, 2, BigDecimal.ROUND_FLOOR).intValue();
				retCut = retCut.add(new BigDecimal(perCut * product.getProductNumber()));
				remain = remain - perCut * product.getProductNumber();
				product.setAfterFullCutPrice(product.getProductPrice().subtract(new BigDecimal(perCut)));
			}
		}
		if (remain > 0) {
			for (OrderProductParam product : tempSorted) {
				if (product.getProductNumber() == 0) {
					continue;
				}
				if (remain > 0 && remain >= product.getProductNumber()) {
					retCut = retCut.add(new BigDecimal(product.getProductNumber()));
					remain = remain - product.getProductNumber();
					product.setAfterFullCutPrice(product.getAfterFullCutPrice().subtract(new BigDecimal(1)));
				}
			}
		}
		if (remain > 0) {
			for (OrderProductParam product : tempSorted) {
				if (product.getProductNumber() == 0) {
					continue;
				}
				BigDecimal perCut = new BigDecimal(remain).divide(new BigDecimal(product.getProductNumber()), 1, BigDecimal.ROUND_FLOOR);
				if (product.getAfterFullCutPrice() == null) {
					if (product.getProductPrice().compareTo(perCut) <= 0) {
						continue;
					}
				} else {
					if (product.getAfterFullCutPrice().compareTo(perCut) <= 0) {
						continue;
					}
				}
				
				retCut = retCut.add(perCut.multiply(new BigDecimal(product.getProductNumber())));
				if (product.getAfterFullCutPrice() == null) {
					product.setAfterFullCutPrice(product.getProductPrice().subtract(perCut));
				} else {
					product.setAfterFullCutPrice(product.getAfterFullCutPrice().subtract(perCut));
				}
				
				break;
			}
		}
		return retCut;
	}
	
	
	public Map<String, List<AmountPromotion>> getDiscountPolicys(List<DiscountRuleParam> ruleParams,
			List<AmountPromotion> amountPromotions, String companyId) {
		Map<String, List<AmountPromotion>> retMaps = Maps.newHashMap();
		for (DiscountRuleParam param : ruleParams) {
			if (!retMaps.containsKey(param.getId())) {
				retMaps.put(param.getId(), Lists.newArrayList());
			}
			for (AmountPromotion promotion : amountPromotions) {
				if (calcAvaliblePromotion(param, promotion, companyId)) {
					retMaps.get(param.getId()).add(promotion);
				}
			}
		}
		for (Entry<String, List<AmountPromotion>> entry : retMaps.entrySet()) {
			for (AmountPromotion promotion : entry.getValue()) {
				promotion.setPromotionConfigs(null);
				promotion.setPromotionAmounts(sortAmountConfig(promotion.getPromotionAmounts()));
			}
		}
		return retMaps;
	}
	
	private List<AmountPromotionConfigAmount> sortAmountConfig(List<AmountPromotionConfigAmount> inList) {
		if (CollectionUtils.isEmpty(inList) || inList.size() < 2) {
			return inList;
		}
		for (int i = 0; i < inList.size(); i++) {
			for (int j = i + 1; j < inList.size(); j++) {
				if (Integer.valueOf(inList.get(i).getRequireAmount()) > Integer.valueOf(inList.get(j).getRequireAmount())) {
					AmountPromotionConfigAmount temp = inList.get(i);
					inList.set(i, inList.get(j));
					inList.set(j, temp);
				}
			}
		}
		return inList;
	}
	
	private boolean calcAvaliblePromotion(DiscountRuleParam param, AmountPromotion amountPromotion, String companyId) {
		return calcPromotionCustomer(param, amountPromotion) && calcPromotionStore(param, amountPromotion)
				&& calcPromotionBrandId(param, amountPromotion) && calcPromotionCategoryId(param, amountPromotion)
				&& calcPromotionAreaId(param, amountPromotion, companyId);
	}
	
	//判断店铺条件
	private boolean calcPromotionStore(DiscountRuleParam param, AmountPromotion amountPromotion) {
		return param.getProductStoreId().equals(amountPromotion.getProductStoreId());
	}
	//判断客户类型条件
	private boolean calcPromotionCustomer(DiscountRuleParam param, AmountPromotion amountPromotion) {
		return DiscountConfigValueEnum.CUSTOMER_ALL.getIndex().equals(amountPromotion.getTargetCustomer())
				|| amountPromotion.getTargetCustomer().equals(param.getCustomerType());
	}
	//判断品牌条件
	private boolean calcPromotionBrandId(DiscountRuleParam param, AmountPromotion amountPromotion) {
		for (AmountPromotionConfig config : amountPromotion.getPromotionConfigs()) {
			if (DiscountConfigValueEnum.BRAND_LIMIT.getIndex().equals(config.getConfigType())) {
				if (DiscountConfigValueEnum.BRAND_LIMIT_ALL.getIndex().equals(config.getConfigValue())) {
					return true;
				}
				for (AmountPromotionConfigBrand configBrand : config.getBrands()) {
					if (param.getBrandId().equals(configBrand.getBrandId())) {
						return true;
					}
				}
			}
		}
		return false;
	}
	//判断区域条件
	private boolean calcPromotionAreaId(DiscountRuleParam param, AmountPromotion amountPromotion, String companyId) {
		for (AmountPromotionConfig config : amountPromotion.getPromotionConfigs()) {
			if (DiscountConfigValueEnum.AREA_LIMIT.getIndex().equals(config.getConfigType())) {
				if (DiscountConfigValueEnum.AREA_LIMIT_DEFAULT.getIndex().equals(config.getConfigValue())) {
					return true;
				} else {
					List<String> geoIds = config.getAreas().stream().map(AmountPromotionConfigArea::getGeoId).distinct().collect(Collectors.toList());
					geoIds.retainAll(param.getGeoIds());
					if (geoIds.size() > 0) {
						return true;
					}
				}
			}
		}
		return false;
	}
	
	//可报价区域条件
//	private boolean calcPromotionDefaultArea(DiscountRuleParam param, AmountPromotion amountPromotion,
//			Map<String, StoreQuoteArea> storeQuoteMaps, String companyId) {
//		String storeId = param.getProductStoreId();
//		List<String> geoIds = param.getGeoIds();
//		if (storeQuoteMaps.containsKey(storeId)) {
//			StoreQuoteArea area = storeQuoteMaps.get(storeId);
//			if (CollectionUtils.isNotEmpty(area.getGarageCompanyIds()) && area.getGarageCompanyIds().contains(companyId)) {
//				return true;
//			}
//			
//			if (StoreAreaTypeEnum.IN.toString().equals(area.getStoreAreaType().toString())
//					&& CollectionUtils.isNotEmpty(area.getStoreAreaCityIds())) {
//				for (String geoId : area.getStoreAreaCityIds()) {
//					if (geoIds.contains(geoId)) {
//						return true;
//					}
//				}
//			} else if (StoreAreaTypeEnum.OUT.toString().equals(area.getStoreAreaType().toString())
//					&& CollectionUtils.isNotEmpty(area.getStoreAreaCityIds())) {
//				boolean notInFlag = true;
//				for (String geoId : area.getStoreAreaCityIds()) {
//					if (geoIds.contains(geoId)) {
//						notInFlag =  false;
//						break;
//					}
//				}
//				return notInFlag;
//			} else if (StoreAreaTypeEnum.OUT.toString().equals(area.getStoreAreaType().toString())
//					&& CollectionUtils.isEmpty(area.getStoreAreaCityIds())) {
//				return true;
//			}
//		}
//		return false;
//	}
	//判断品类条件
	private boolean calcPromotionCategoryId(DiscountRuleParam param, AmountPromotion amountPromotion) {
		for (AmountPromotionConfig config : amountPromotion.getPromotionConfigs()) {
			if (DiscountConfigValueEnum.CATEGORY_LIMIT.getIndex().equals(config.getConfigType())) {
				if (DiscountConfigValueEnum.CATEGORY_LIMIT_ALL.getIndex().equals(config.getConfigValue())) {
					return true;
				}
				for (AmountPromotionConfigCategory configCategory : config.getCategorys()) {
					if (configCategory.getCategoryName().equals(param.getCategoryName())) {
						return true;
					}
				}
			}
		}
		return false;
	}
	
	public static void main(String[] args) {
		System.out.println(10 / 3);
	}
}
